var http = require('http'),
	https = require('https'),
	net = require('net'),
	Socket = net.Socket,
	iconv = require('iconv-lite'),
	crypto  = require('crypto'),
	redis = require('redis'),
	querystring = require('querystring'),
	fs = require('fs'),
	app = require('./app'),
	ipSection = require('./ipSection');

var redis_db = app.config['redis_db'];
var redisclient = redis.createClient(redis_db.port,redis_db.host);
redisclient.auth(redis_db.password);
redisclient.select(1)

var redis_db = app.config['redis_db'];
var redisAvlProxy = redis.createClient(redis_db.port,redis_db.host);
redisAvlProxy.auth(redis_db.password);

//日志
var loggerError = require('tracer').console({
	transport : function(data) {
		//console.log(data.output);
		fs.open('./error.log', 'a', 0666, function(e, id) {
			fs.write(id, data.output+"\n", null, 'utf8', function() {
				fs.close(id, function() {
				});
			});
		});
	},
	level : 'logError',
	methods : [ 'logError',],

});

var loggerInfo = require('tracer').console({
	transport : function(data) {
		//console.log(data.output);
		fs.open('./info.log', 'a', 0666, function(e, id) {
			fs.write(id, data.output+"\n", null, 'utf8', function() {
				fs.close(id, function() {
				});
			});
		});
	},
	level : 'logInfo',
	methods : [ 'logInfo',],

});
var ipSection = ipSection.ipSection;
var checkPortTimeout = app.config['checkPortTimeout'];
var checkProxyTimeout = app.config['checkProxyTimeout'];
var threadNowNum = app.config['threadNowNum'];
var threadMaxNum = app.config['threadMaxNum'];
var checkPortList = app.config['checkPortList'];
var checkPortListLen = app.config['checkPortListLen'];

var http_md5 = app.config['http_md5'];
var https_md5 = app.config['https_md5'];
var ipstart = app.config['ipstart'];
var skip = app.config['skip'];
var scanCount = 0;//总共扫描的ip数

//启用socket开始扫描
checkIpAndPortStatus = function(proxy, callback) {
	//console.log(proxy['ip']+'-'+proxy['port']+' timeout');
	var dateS1 = new Date();
	host = proxy['ip'];
	port = proxy['port'];
    var socket = new Socket();
    socket.on('connect', function() {
        socket.destroy();
		var dateS2 = new Date();
		redisclient.lpush('piplist2',JSON.stringify(proxy));

		proxy['portchecktime'] = dateS2.getTime() - dateS1.getTime();
        checkProxy(proxy, callback);
    });
    socket.setTimeout(checkPortTimeout);//设置socket超时时间
    socket.on('timeout', function() {
        socket.destroy();
		delChProxy(proxy);
        callback(proxy, 'timeout');
    });
    socket.on('error', function(exception) {
    	loggerError.logError(exception+'--'+JSON.stringify(proxy));
    	//console.log(exception);
        socket.destroy();
		delChProxy(proxy);
        callback(proxy, 'closed');
    });
    //console.log(port+host);
    socket.connect(port, host);
};

//累加存活时间
chProxy = function(proxy){
	_stimekey = proxy["ip"]+":"+proxy["port"];
	redisclient.hget('iptime',_stimekey,function(err,data){
		var dateS1 = new Date();
		ttime = dateS1.getTime() / 1000;
		try{
			tdata = JSON.parse(data);			
			if(tdata["stime"]!=undefined && tdata["time"]!=undefined){						
				tdata["stime"] = tdata["stime"] + ttime - tdata["time"];
				tdata["time"] = ttime;	
			}else{
				tdata = {}
				tdata["stime"] = 600;
				tdata["time"] = ttime;
			}
		}catch(err){
			tdata = {}
			tdata["stime"] = 600;
			tdata["time"] = ttime;
		}
		redisclient.hset('iptime',_stimekey,JSON.stringify(tdata));
	});
}
//重置存活时间
delChProxy = function(proxy){
	_stimekey = proxy["ip"]+":"+proxy["port"];
	redisclient.hdel('iptime',_stimekey);
}

//检查代理是否可用
checkProxy = function(proxy,callback){
	var header = app.config['head_proxy'];
	header['host'] = proxy['ip'];
    header['port'] = proxy['port'];
	/*var body = "";
    header['host'] = proxy['ip'];
    header['port'] = proxy['port'];
        
    console.log('正检测：'+proxy['ip']+":"+proxy['port']);
    var req = http.request(header, function(res) {
    	res.setEncoding('binary');
    	var body = "";
		res.on('data',function(d){
			body += d;
		}).on('end', function(){
			var hashmsg=md5file(body);
			if(hashmsg.toLowerCase()==http_md5.toLowerCase()){
				checkProxyIsAnon(proxy,callback);
			}else{
				callback(proxy);
			}
		 });
    }).on('error', function(e) {
    	loggerError.logError(e);
    	callback(proxy);
    });

    req.setTimeout(checkProxyTimeout, function(){
        req.abort();
    });
    req.end();*/


	//以下是接受数据的代码
	var req = http.request(header, function(res) {
		if( ( res.statusCode == 304 && typeof(res.headers['content-type']) == 'undefined' ) ||  (res.statusCode == 200 && res.headers['content-type'] == 'text/javascript; charset=UTF-8') ){
			checkProxyIsAnon(proxy,callback);
			console.log(proxy)
			//存活时间
			chProxy(proxy)
		}else{
			delChProxy(proxy);
			callback(proxy);
		}
	}).on('error', function(e) {
		delChProxy(proxy);
		callback(proxy);
	});
	req.setTimeout(5000, function(){
		req.abort();
	});
	req.end();

}

//检查代理是否是高度匿名
checkProxyIsAnon = function(proxy,callback){
	var header = app.config['head_isanon'];
	var body = "";
	hidetype = 2;
    header['host'] = proxy['ip'];
    header['port'] = proxy['port'];
    //console.log('正检测：'+proxy['ip']+":"+proxy['port']);
    var req = http.request(header, function(res) {
    	var body = "";
    	res.setEncoding('binary');
		res.on('data',function(d){
			body += d;
		}).on('end', function(){
			body = iconv.decode(new Buffer(body,'binary'),'gbk');
			re =new RegExp(proxy['ip']);
			if(re.test(body)){// 判断是否是高度匿名
				hidetype = 1;
			}
			proxy['hidetype'] = hidetype;
			checkHttpsProxy(proxy,callback);
		 });
    }).on('error', function(e) {
		proxy['hidetype'] = hidetype;
    	checkHttpsProxy(proxy,callback);
    });

    req.setTimeout(checkProxyTimeout, function(){
        req.abort();
    });
    req.end();
}

//检查是否支持https
checkHttpsProxy = function(proxy,callback){
	var header = app.config['head_https'];
	var body = "";
    header['host'] = proxy['ip'];
    header['port'] = proxy['port'];
	proxy['ishttps'] = 0;
    
    //console.log('正检测：'+proxy['ip']+":"+proxy['port']);

    var req = http.request(header, function(res) {
    	res.setEncoding('binary');
    	var body = "";
		res.on('data',function(d){
			body += d;
		}).on('end', function(){
			var hashmsg=md5file(body);
			
			if(hashmsg.toLowerCase()==https_md5.toLowerCase()){
				proxy['ishttps'] = 1;
			}
			redisclient.lpush('iplist',JSON.stringify(proxy));
			redisclient.sadd('h_iplist',JSON.stringify(proxy));
			callback(proxy);
		 });
    }).on('error', function(e) {
		redisclient.lpush('iplist',JSON.stringify(proxy));
		redisclient.sadd('h_iplist',JSON.stringify(proxy));
    	callback(proxy);
    });

    req.setTimeout(checkProxyTimeout, function(){
        req.abort();
    });
    req.end();
}

md5file = function(data){
	var hasher=crypto.createHash("md5");
	m = hasher.update(data);
	var hashmsg=hasher.digest('hex');
	return hashmsg; 
}

threadIncr = function(){
	threadNowNum++;
	if(threadNowNum>threadMaxNum+10){
		console.log("threadNum 超过预料值"+threadNowNum);
	}
}
threadDecr = function(proxy){
	threadNowNum--;
	if(threadNowNum<0){
		console.log("threadNum 小于0");
	}
}

//var portlist = [80,8080,3128,8888,83,85,6675];
var portlist = app.config['portlist'].slice(0);
produce = function(){
	var len = 0;
	for(var j in checkPortList){
		len++;
	}
	if(len>=checkPortListLen){
		console.log(" len max");
		return false;
	}
	console.log(len);

	for(var i in ipSection){
		port = portlist[0];
		//
		var section = ipSection[i];
		if(ipstart==0){
			//console.log('start == 0');
			start = ip2int(section[0]);
		}else{
			start = ipstart;
		}
		stop = ip2int(section[1]);
		if(start+checkPortListLen<stop){
			stop = start+checkPortListLen;
			ipstart = stop;
			//console.log('stop===');
		}else{
			portlist.shift();
			ipstart = 0;
		}

		if(portlist.length==0){
			delete ipSection[i];
			//portlist = [80,8080,3128,8888,83,85];
			portlist = app.config['portlist'].slice(0);
		}
		var proxy = {};
		console.log(start+"--"+stop+'--'+port);
		
		for(var j=start;j<=stop;j=j+skip){
			scanCount++;
			var proxy = {};
			var ip = proxy['ip'] = int2ip(j);
			var port = proxy['port'] = port;
			//console.log(JSON.stringify(proxy)+'--');
			checkPortList[ip+port] = proxy;
		}

		//进度
		rate = {};
		rate['ipsection'] = section[0];
		rate['ipstart'] = start;
		rate['port'] = port;
		rate['threadMaxNum'] = threadMaxNum;
		rate['scanCount'] = scanCount;
		rate['threadNowNum'] = threadNowNum;
		writeRate(rate);

		break;
	}
}


function ip2int(ip){
   ip_arr = ip.split('.'); 
   iplong = (16777216 * parseInt(ip_arr[0])) + (65536 * parseInt(ip_arr[1])) + (256 * parseInt(ip_arr[2])) + parseInt(ip_arr[3]);  
   return iplong; 
}

function int2ip(proper_address){
    proper_address = proper_address>>>0;
    var output = false; 
    if (!isNaN(proper_address) && (proper_address >= 0 || proper_address <= 4294967295)) {
      output = Math.floor(proper_address / Math.pow(256, 3)) + '.' +
               Math.floor((proper_address % Math.pow(256, 3)) / Math.pow(256, 2)) + '.' +
               Math.floor(((proper_address % Math.pow ( 256, 3)) % Math.pow(256, 2)) / Math.pow(256, 1)) + '.' +
               Math.floor((((proper_address % Math.pow ( 256, 3)) % Math.pow(256, 2)) % Math.pow(256, 1)) / Math.pow(256, 0));
    }
    return output;
}

/**
*
* 记录进度
*/
function writeRate(rate){
	fs.writeFileSync('rate.txt', JSON.stringify(rate));
}

/*
*
* 载入进度
*/
function loadRate(callback){
	path = 'rate.txt';
	if(!fs.existsSync(path)){
		callback();
		return false;
	}

	rateStr = fs.readFileSync(path);
	rateJson = JSON.parse(rateStr);
	ipstart = rateJson['ipstart'];
	scanCount = rateJson['scanCount'];
	p = rateJson['port'];
	for(var i in ipSection){
		if(ipSection[i][0]==rateJson['ipsection']){
			break;
		}else{
			delete ipSection[i];
		}
	}

	for(var i=0;i<portlist.length;i++){
		pp = portlist.shift();
		if(p==pp){
			portlist.unshift(pp);
			break;
		}
	}
	console.log(ipstart+'---'+portlist);
	callback();
}




//调用
start = function(){
	if(threadNowNum>=threadMaxNum){
		return false;
	}

	for(var i in checkPortList){
		//console.log(i+'key');
		proxy = checkPortList[i];
		threadIncr();
		//console.log(JSON.stringify(proxy)+'--');
		checkIpAndPortStatus(proxy,threadDecr);
		delete checkPortList[i];
		break;
	}	
}

//开启web接收检测ip
http.createServer(function (req, res) {
    var postData = '';
    // 设置接收数据编码格式为 UTF-8
    req.setEncoding('utf8');
    // 接收数据块并将其赋值给 postData
    req.addListener('data', function(postDataChunk) {
        postData += postDataChunk;
    });

    req.addListener('end', function() {
		var postJson = querystring.parse(postData);
		//console.log(postData);
		var listIp = postJson.ip.split(',');
		var ipObj = {};
		for(var i in listIp){
			ipArr = listIp[i].split(':');
			ipObj = {};
			var ip = ipObj['ip'] = ipArr[0];
			var port = ipObj['port'] = ipArr[1];
			//checkPortList.push(ipObj);
			checkPortList[ip+port] = ipObj;

			loggerInfo.logInfo(JSON.stringify(ipObj));
			redisclient.sadd('ciplist',JSON.stringify(ipObj));
		}

		res.write(postData);
        // 数据接收完毕，执行回调函数
    });

    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(6337, '127.0.0.1');

/*
proxy = {};
//proxy['ip'] = '202.171.253.108';
//proxy['port'] = 80;

proxy['ip'] = '192.168.7.254';
proxy['port'] = 8087;
checkPortList.push(proxy);
*/

function init(){
	//setInterval(produce,300);
	setInterval(start,1);
	setInterval(start,1);
}

loadRate(init);
